package com.youlu.campus.web.data.english;


import com.alibaba.fastjson.JSON;
import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.base.order.GoodsInfo;
import com.youlu.campus.base.order.enums.OrderPayTypeEnum;
import com.youlu.campus.entity.UserPO;
import com.youlu.campus.entity.VO.PlaceOrderReq;
import com.youlu.campus.entity.domain.WechatH5PayConfigDomain;
import com.youlu.campus.entity.english.ActivityGroupQaType;
import com.youlu.campus.entity.english.ActivityQaFeeDetail;
import com.youlu.campus.entity.english.UserCompetitionFee;
import com.youlu.campus.entity.english.vo.request.CompetitionPlaceOrderCommand;
import com.youlu.campus.service.activity.ActivityService;
import com.youlu.campus.service.english.CompetitionUserInviteService;
import com.youlu.campus.service.english.UserCompetitionFeeService;
import com.youlu.campus.web.order.entity.OrderPO;
import com.youlu.campus.web.order.service.OrderBaseService;
import com.yuelin.infrastructure.quantum.common.QResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CompetitionFeeService extends OrderBaseService {

    @Autowired
    private UserCompetitionFeeService userCompetitionFeeService;


    private final static String LOCK_ORDER = "campus:english:order:%s:%s:%s";

    @Value("${sys.pay.wx.bizCompetitionFrontDomain}")
    private String bizCompetitionFrontDomain;

    @Autowired
    private ActivityService activityService;

      @Autowired
      private CompetitionUserInviteService competitionUserInviteService;

      public Integer getStatusByOrderNo(String orderNo){
          UserCompetitionFee userCompetitionFee = userCompetitionFeeService.findOrderNo(orderNo);
          if(Objects.isNull(userCompetitionFee)){
              throw new BusinessException("该订单不存在");
          }
         return userCompetitionFee.getStatus();
      }


    public Map<String,String> placeOrder(CompetitionPlaceOrderCommand command){
        UserPO currentUser = command.getCurrentUser();
        String activityGroupId = command.getActivityGroupId();
        String feeTypeCode = command.getFeeTypeCode();
        String userId = currentUser.getId();
        log.info("用户 - > {} 购买组 -> {} 费用类别 ",currentUser.getId(),activityGroupId,feeTypeCode);
        String lockKey = String.format(LOCK_ORDER,  userId, activityGroupId, feeTypeCode);
        log.info("【订单锁】获取锁信息->{}", lockKey);
        Boolean existKey = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 5L, TimeUnit.SECONDS);
        if (Objects.nonNull(existKey)&&!existKey) {
            throw new BusinessException("对不起哦，服务繁忙,稍后重试");
        }
        UserCompetitionFee userCompetitionFee = userCompetitionFeeService.placeOrder(command);
        log.info("start prepay ----userId {} | group {} | fee {} | clientIP {}",userId,activityGroupId,feeTypeCode, command.getClientIp());
        OrderPO orderPO = new OrderPO();
        orderPO.setOrderNo(userCompetitionFee.getOrderNo());
        orderPO.setSource(1);
        orderPO.setPayType(OrderPayTypeEnum.WX.getCode());
        GoodsInfo goods = new GoodsInfo();
        goods.setGoodsName("英语大赛-"+userCompetitionFee.getActivityGroupName());
        orderPO.setGoods(goods);
        orderPO.setPayPrice(userCompetitionFee.getPrice());
        orderPO.setClientIp(command.getClientIp());
        orderPO.setTotalPrice(userCompetitionFee.getPrice());
        orderPO.setTransactionId(userCompetitionFee.getOrderNo());
        orderPO.setOpenId(currentUser.getOpenId());
        orderPO.setPlatform(command.getPlatform());
        orderPO.setUserPO(currentUser);
        orderPO.setPlatform("wechat-h5");
        orderPO.setUrl(bizCompetitionFrontDomain+"/contest-h5/index.html#/pages/contest-pay-order/");
        Date now = new Date();
        orderPO.setNonceStr("" + now.getTime());
        orderPO.setTimestampStr("" + now.getTime() / 1000);
        orderPO.setAppId(userCompetitionFee.getAppId());
        Map<String, String> result = new HashMap<>(30);
        //获取预支付参数
        QResult<Map<String, String>> uniOrderResult = super.getUniOrderResult(orderPO);
        log.info("【英语竞赛】user预支付参数结果为:{}", JSON.toJSONString(uniOrderResult));
        // 支付成功
        if (uniOrderResult.code == 0) {
            result = uniOrderResult.data;
            log.info("英语竞赛  userId {} |  group {} | fee {} | result {}",userId , activityGroupId,result);
        } else {
            log.error("【英语竞赛】  userId {} |  group {} | fee {} | error msg {} ",userId , activityGroupId,uniOrderResult.msg);
        }
        result.put("payFeeType", "1");
        result.put("payDesc", "微信支付");
        if ("wechat-h5".equals(orderPO.getPlatform())) {
            WechatH5PayConfigDomain config = activityService.getPayConfig(currentUser, orderPO.getUrl(),
                    orderPO.getNonceStr()
                    , orderPO.getTimestampStr());
            result.put("appId", config.getAppId());
            result.put("signature", config.getSignature());
            result.put("nonceStr", config.getNonceStr());
            result.put("timeStamp", config.getTimestamp());
            result.put("jsApiList", JSON.toJSONString(config.getJsApiList()));
        }
        return result;
    }

    public void notifyPay(String orderNo,String transactionId){
        log.info("【英语大赛】pay notify orderNo {} | transactionId {} ",orderNo,transactionId);
        UserCompetitionFee userCompetitionFee = userCompetitionFeeService.findOrderNo(orderNo);
        if(Objects.isNull(userCompetitionFee)){
            log.error("【英语大赛】pay notify orderNo {} | transactionId {} 订单号不存在 ",orderNo,transactionId);
            return;
        }
            List<ActivityGroupQaType> updateQaType = userCompetitionFee.getBuyQaTypeList().stream().map(qaType -> {
                //不等于题库练习
               if(!ActivityQaFeeDetail.QA_FEE.equals(userCompetitionFee.getFeeTypeCode())){
                   if (ActivityGroupQaType.QA_CHU_SAI.equals(qaType.getCode())) {
                       qaType.setLock(Boolean.TRUE);
                   }
               }
                return qaType;
            }).collect(Collectors.toList());
        Query query = new Query();
        query.addCriteria(Criteria.where("orderNo").is(orderNo));
        Date now = new Date();
        Update update = new Update();
        update.set("status",1);
        update.set("payTime",now);
        update.set("updatedTime",now);
        update.set("transactionId",transactionId);
        update.set("buyQaTypeList",updateQaType);
        UpdateResult updateResult = this.mongoTemplate.updateFirst(query, update, UserCompetitionFee.class);
        if(updateResult.getModifiedCount()>0){
            userCompetitionFee.setBuyQaTypeList(updateQaType);
            userCompetitionFee.setStatus(1);
            userCompetitionFeeService.setUserQaOrder(userCompetitionFee);
            competitionUserInviteService.updateInviteInfo(userCompetitionFee.getActivityId(), userCompetitionFee.getUserId(),userCompetitionFee.getAppId(),"wechat-h5");
        }
    }

    @Override
    public Map<String, String> placeOrder(PlaceOrderReq req) {
        return null;
    }

    @Override
    public boolean handlePayNotify(OrderPO orderPO) {
        return false;
    }
}
